`include "defines.svh"
`include "CP0Defines.svh"
module DcacheWen(
    input logic [11:0]addr,
    input logic [2:0]DMOp,
    input logic [31:0]MEM_Data_Writed, //data ready to write Cache, pre_work in CacheWen
    input logic MEM_DMWr,
    input ExceptionType MEM_ExceptionType,
    input logic DMRd,
    input ExceptionType WB_ExceptionType,
    output logic [31:0]  DataToDcache, //data write to Cache 
    output logic [3:0]   cache_wen,       //�ֽ��ź�дʹ��
    output ExceptionType MEM_ExceptionTypeNew
);

  logic [3:0]               StoreByteWen;
  logic [31:0]              StoreByteData; //预处?
  always_comb begin
    case(addr[1:0])
      2'b00:begin
            StoreByteWen      = 4'b0001;
            StoreByteData     = {24'b0 , MEM_Data_Writed [7:0]};
      end
      2'b01:begin
            StoreByteWen      = 4'b0010;
            StoreByteData     = {16'b0 , MEM_Data_Writed [7:0] , 8'b0};
      end
      2'b10:begin
            StoreByteWen      = 4'b0100;
            StoreByteData     = {8'b0 , MEM_Data_Writed [7:0] , 16'b0};
      end
      2'b11:begin
            StoreByteWen      = 4'b1000;
            StoreByteData     = {MEM_Data_Writed [7:0] , 24'b0};
      end
      default:begin
            StoreByteWen      = 4'b0000; 
            StoreByteData     = '0;
      end
    endcase

  end

  always_comb begin
    if(WB_ExceptionType!=`NoException)begin
      cache_wen = 4'b0000;
      DataToDcache = '0;
    end
    else if(MEM_DMWr) begin
      case(DMOp)
        `word: begin //SW
          cache_wen = 4'b1111;
          DataToDcache = MEM_Data_Writed;
        end
        `half_sign,`half_zero: begin //SH
          if(addr[1] == 1'b0)begin
            cache_wen = 4'b0011;
            DataToDcache = {16'b0,MEM_Data_Writed[15:0]};
          end
          else begin
            cache_wen = 4'b1100;
            DataToDcache = {MEM_Data_Writed[15:0],16'b0};
          end
        end
        `byte_sign,`byte_zero: begin //SB
            cache_wen = StoreByteWen;
            DataToDcache = StoreByteData;
        end
        default: begin
            cache_wen = 4'b0000;
            DataToDcache = '0;
        end
      endcase
    end 
    else begin
      cache_wen = 4'b0000;
      DataToDcache = '0;
    end
  end

    assign MEM_ExceptionTypeNew.WrongAddrInIF=MEM_ExceptionType.WrongAddrInIF;
    assign MEM_ExceptionTypeNew.WrongAddrInDataWr=(MEM_DMWr&&((DMOp==`half_sign&&addr[0]!=0)||(DMOp==`half_zero&&addr[0]!=0)||(DMOp==`word&&addr[1:0]!=2'b00)));
    assign MEM_ExceptionTypeNew.WrongAddrInDataRd=((DMRd)&&((DMOp==`half_sign&&addr[0]!=0)||(DMOp==`half_zero&&addr[0]!=0)||(DMOp==`word&&addr[1:0]!=2'b00)));
    assign MEM_ExceptionTypeNew.Overflow=MEM_ExceptionType.Overflow;
    assign MEM_ExceptionTypeNew.Syscall=MEM_ExceptionType.Syscall;
    assign MEM_ExceptionTypeNew.Break=MEM_ExceptionType.Break;
    assign MEM_ExceptionTypeNew.ReservedInstr=MEM_ExceptionType.ReservedInstr;
    assign MEM_ExceptionTypeNew.Interrupt=MEM_ExceptionType.Interrupt;
    assign MEM_ExceptionTypeNew.Eret=MEM_ExceptionType.Eret;
endmodule